// 2025/3/9
// https://leetcode.cn/problems/validate-binary-search-tree/description/?envType=study-plan-v2&envId=top-100-liked
// 验证二叉搜索树

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
    public:
        pair<pair<int, int>, bool> find(TreeNode* root)
        {
            if(!root->left && !root->right)
                return (pair<pair<int, int>, bool>){{root->val, root->val}, true};
    
            if(!root->left)
            {
                pair<pair<int, int>, bool> right = find(root->right);
                if(!right.second || right.first.first <= root->val) 
                    return (pair<pair<int, int>, bool>){{0, 0}, false};
                else
                    return (pair<pair<int, int>, bool>){{root->val, right.first.second}, true};
            }
            else if(!root->right)
            {
                pair<pair<int, int>, bool> left = find(root->left);
                if(!left.second || left.first.second >= root->val) 
                    return (pair<pair<int, int>, bool>){{0, 0}, false};
                else
                    return (pair<pair<int, int>, bool>){{left.first.first, root->val}, true};
            }
            else
            {
                pair<pair<int, int>, bool> right = find(root->right);
                pair<pair<int, int>, bool> left = find(root->left);
                if(!right.second || right.first.first <= root->val || !left.second || left.first.second >= root->val) 
                    return (pair<pair<int, int>, bool>){{0, 0}, false};
                else
                    return (pair<pair<int, int>, bool>){{left.first.first, right.first.second}, true};
            }
        }
    
        bool isValidBST(TreeNode* root) {
            return find(root).second;
        }
    };